<template>
  <div class="event-setting-container">
    <SectionTitle title="事件列表">
      <span class="title-tip">(已添加的事件可在配置流程节点时设置，审批中时生效)</span>
      <div class="options-btn-group">
        <PlainCreateBtn @click="createNewRow">添加</PlainCreateBtn>
        <el-button
          :disabled="!curSelectedRows.length"
          size="small"
          type="danger"
          plain
          class="option-btn"
          @click="handleRowsDel"
        >删除</el-button>
      </div>
    </SectionTitle>
    <DynamicEditTable
      ref="dynamicEditTableRef"
      v-model="orders"
      :list-setting="listSetting"
      :show-serial="false"
      :show-add-btn="false"
      :default-params="defaultOrderItem"
      :order-private-id="orderPrivateId"
      :fixed="false"
      is-edit
      can-empty
      show-selection
      @onRowDel="handleOrderRowDelete"
      @copyItem="handleEventTargetNodesChange"
      @changeValue="emitEventNames"
      @selectManualChange="handleSelectManualChange"
      @inputChange="handleSelectManualChange"
      @onSelectChange="onSelectChange"
      @orderPrivateIdChange="orderPrivateIdChange"
    />
  </div>
</template>

<script>
import SectionTitle from '@/components/Title';
import DynamicEditTable from '@/components/Common/dynamicEditTable';
import { showModal } from '@/utils/message';
import { EventBus } from '@/utils/eventBus';
import { CUSTOM_PROCESS_EVENT } from '@/utils/const/process';
export default {
  name: 'EventSetting',
  components: {
    SectionTitle,
    DynamicEditTable
  },
  props: {
    configFields: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      orders: [],
      orderPrivateId: 0,
      defaultOrderItem: {
        customizeState: true
      },
      targetNodeOptions: [],
      curSelectedRows: []
    };
  },
  computed: {
    operateList() {
      return [
        { label: '字段隐藏', value: CUSTOM_PROCESS_EVENT.TURN_ON_FIELD_HIDE },
        { label: '字段显示', value: CUSTOM_PROCESS_EVENT.TURN_ON_FIELD_DISPLAY },
        { label: '启用填写', value: CUSTOM_PROCESS_EVENT.TURN_ON_FIELD_ENABLE },
        { label: '启用必填', value: CUSTOM_PROCESS_EVENT.TURN_ON_FIELD_REQUIRED },
        { label: '节点只读', value: CUSTOM_PROCESS_EVENT.TURN_ON_FIELD_READ_ONLY }
      ];
    },
    listSetting() {
      return [{
        label: '事件名称',
        type: 'inputText',
        maxlength: 12,
        width: '250px',
        keyword: 'name',
        placeholder: '请输入',
        isRequired: true
      }, {
        label: '事件动作',
        type: 'select',
        width: '250px',
        keyword: 'operate',
        isRequired: true,
        keyName: 'value',
        labelName: 'label',
        options: this.operateList
      }, {
        label: '目标字段',
        type: 'select',
        width: '250px',
        keyword: 'target',
        isRequired: true,
        keyName: 'key',
        multiple: true,
        collapseTags: true,
        options: this.configFields
      }, {
        label: '目标节点',
        type: 'select',
        width: '250px',
        keyword: 'targetNodes',
        isRequired: false,
        multiple: true,
        collapseTags: true,
        options: this.targetNodeOptions
      }];
    }
  },
  watch: {
    orders: {
      handler() {
        this.statusCheck();
      },
      deep: true
    }
  },
  created() {
    this.statusCheck();
    EventBus.$on('formOptionsChange', configObj => {
      const eventType = ['clearStatistics', 'removeStatistics', 'remove'];
      if (eventType.includes(configObj.type)) {
        this.resetOrderTarget(configObj);
      }
    });
    // 同步流程设计节点数据，获取目标可节点选项
    EventBus.$on('processChange', data => {
      this.targetNodeOptions = this.setTargetNodes(data.childNode);
      this.$nextTick(() => {
        this.formatTargetNodes();
      });
    });
    // 流程设计审批事件变更 -> 同步变更事件设置目标节点选项，两者对应
    EventBus.$on('nodeApprovalEventsChange', data => {
      const { id, setEvents } = data;
      this.orders.forEach(item => {
        const orderId = item.id || -(Number(item.orderPrivateId));
        if (!Array.isArray(item.targetNodes)) item.targetNodes = [];
        if (!(setEvents || []).includes(orderId)) {
          item.targetNodes = item.targetNodes.filter(i => i !== id);
        } else {
          !item.targetNodes.includes(id) && item.targetNodes.push(id);
        }
      });
    });
  },
  methods: {
    onSelectChange(list) {
      this.curSelectedRows = list;
    },
    orderPrivateIdChange(num) {
      if (!num) return;
      this.orderPrivateId = num;
    },
    /*
      事件名称/目标节点变更，同步节点设置审批事件数据
      不能直接在changeValue上同步，因为会导致接口返回数据马上同步
      而历史数据目标节点栏是空的，会把节点设置的已保存审批事件给清空
    */
    handleSelectManualChange(data) {
      if (['name', 'targetNodes'].includes(data.key)) {
        this.handleEventTargetNodesChange();
      }
    },
    // 会影响到 目标节点 -> 节点审批事件 数据同步的操作都要执行改方法
    handleEventTargetNodesChange() {
      this.$nextTick(() => {
        EventBus.$emit('eventTargetNodesChange', this.orders);
      });
    },
    createNewRow() {
      this.$refs['dynamicEditTableRef'].addValue();
      this.$refs['dynamicEditTableRef'].validate().catch(() => {
        this.statusCheck();
      });
    },
    handleOrderRowDelete() {
      this.statusCheck();
      this.handleEventTargetNodesChange();
    },
    statusCheck() {
      this.$emit('statusCheck');
    },
    handleRowsDel() {
      showModal('确认删除已选中的数据吗？').then(_ => {
        while (this.curSelectedRows.length) {
          const curRow = this.curSelectedRows.pop();
          for (let index = this.orders.length - 1; index >= 0; index--) {
            if (this.orders[index].orderPrivateId === curRow.orderPrivateId) {
              this.orders.splice(index, 1);
            }
          }
        }
        this.emitEventNames();
        this.statusCheck();
        this.handleEventTargetNodesChange();
      });
    },
    // 表单设计删除字段后，已关联的事件字段要同步删除
    resetOrderTarget(configObj) {
      const optionType = configObj.data.type;
      if (optionType === 'subform') {
        const subformFieldKeys = configObj.changeStatistics;
        if (Array.isArray(subformFieldKeys) && subformFieldKeys.length) {
          subformFieldKeys.forEach(key => {
            this.targetDisassociate(key);
          });
        } else {
          this.targetDisassociate(subformFieldKeys);
        }
      } else {
        this.targetDisassociate(configObj.data.key);
      }
    },
    isEmpty(obj) {
      if (!obj) return false;
      return Object.keys(obj).length <= 0;
    },
    // 获取流程设计类型为审批-0和加签-5的节点
    setTargetNodes(data) {
      const targetNodes = [];
      const dfs = (curNode) => {
        if (!curNode || this.isEmpty(curNode)) return;
        // 排除开始结束节点
        if (!curNode.root && !curNode.isEnd) {
          // 审批-0 || 加签-5 节点
          if ([0, 5].includes(curNode.nodeType)) {
            targetNodes.push({ id: curNode.id, name: curNode.nodeName });
            // 同步节点审批事件历史数据至目标节点
            EventBus.$emit('nodeApprovalEventsChange', curNode);
          }
        }
        if (!this.isEmpty(curNode.childNode)) {
          dfs(curNode.childNode);
        }
        if (curNode.conditionNodes && curNode.conditionNodes.length) {
          for (let i = 0; i < curNode.conditionNodes.length; i++) {
            dfs(curNode.conditionNodes[i]);
          }
        }
      };
      dfs(data);
      return targetNodes;
    },
    // 选中的审批节点若已被删除，移除
    formatTargetNodes() {
      if (!Array.isArray(this.orders) || !this.orders.length) return;
      this.orders.forEach(item => {
        if (Array.isArray(item.targetNodes) && item.targetNodes.length) {
          item.targetNodes = item.targetNodes.filter(id => {
            return this.targetNodeOptions.some(targetNodes => targetNodes.id === id);
          });
        }
      });
    },
    targetDisassociate(key) {
      this.orders.forEach(item => {
        if (Array.isArray(item.target) && item.target.length) {
          const targetNum = item.target.length;
          for (let i = targetNum - 1; i >= 0; i--) {
            if (item.target[i] === key) {
              item.target.splice(i, 1);
              break;
            }
          }
        }
      });
    },
    emitEventNames() {
      const names = this.orders.filter(item => item.name).map(item => {
        return {
          value: -item.orderPrivateId,
          label: item.name,
          target: item.target ? item.target.join(',') : '',
          operate: item.operate || null,
          targetNodes: item.targetNodes ? item.targetNodes.join(',') : ''
        };
      });
      this.$emit('eventNameChange', names);
    },
    validateForm() {
      return new Promise((resolve, reject) => {
        this.$refs['dynamicEditTableRef'].validate().then(() => {
          const sameName = [];
          const nameMap = new Map();
          this.orders.forEach(item => {
            nameMap.has(item.name) ? sameName.push(item.name) : nameMap.set(item.name, true);
          });
          sameName.length ? reject(`高级设置-事件设置存在相同的事件名称：${sameName.join('、')}`) : resolve(true);
        }).catch(() => {
          reject('请完善高级设置-事件设置信息');
        });
      });
    },
    getData() {
      return this.orders.map(item => {
        return {
          id: -item.orderPrivateId,
          name: item.name,
          operate: item.operate,
          target: item.target.join(),
          targetNodes: item.targetNodes.join()
        };
      });
    },
    setData(list) {
      if (Array.isArray(list) && list.length) {
        this.orders = list.map((item, index) => {
          item.orderPrivateId = -item.id;
          item.target = item.target && item.target.split(',');
          item.targetNodes = item.targetNodes && item.targetNodes.split(',');
          if (index === list.length - 1) {
            this.orderPrivateId = -item.id;
          }
          return item;
        });
      }
    },
    // 引用表单设计使清除目标字段
    initOrdersField() {
      this.orders.forEach(i => {
        i.target = '';
      });
    }
  }
};
</script>

<style scoped lang="scss">
.event-setting-container {
  .title-tip {
    font-size: 14px;
    color: #999;
    font-weight: normal;
    margin-left: 6px;
  }
  .options-btn-group {
    position: absolute;
    right: 0;
    ::v-deep .el-button {
      padding-left: 12px;
      padding-right: 12px;
    }
  }
  & ::v-deep {
    .filterableSelect {
      width: 100%;
    }
    .el-button--text:not(:first-child)::before {
      left: -8px;
    }
    .table-empty {
      height: 48px;
    }
    .el-input__inner {
      height: 48px !important;
    }
  }
}
</style>
